package com.whfc.fse.xxl.job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.whfc.XxlJobConfig;
import com.whfc.base.dto.AppSyncDTO;
import com.whfc.base.service.SyncConfigService;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.DevicePlatform;
import com.whfc.common.enums.SyncPlatform;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.MathUtil;
import com.whfc.fse.dto.FseCraneDTO;
import com.whfc.fse.dto.FseCraneDataDTO;
import com.whfc.fse.dto.FseCraneRecordDTO;
import com.whfc.fse.enums.FseWarnRuleType;
import com.whfc.fse.manager.FseCraneSZJDataMgr;
import com.whfc.fse.service.FseCraneService;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component
@ConditionalOnBean(XxlJobConfig.class)
public class FseCraneSZJDataJob {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @DubboReference(interfaceClass = SyncConfigService.class, version = "1.0.0")
    private SyncConfigService syncConfigService;

    @Autowired
    private FseCraneService fseCraneService;

    @Autowired
    private FseCraneSZJDataMgr fseCraneSZJDataMgr;

    @Resource(name = "baseRabbitTemplate")
    private AmqpTemplate amqpTemplate;

    /**
     * 宇泛数智建平台-实时数据
     */
    @XxlJob("szj-craneData")
    public void getCraneData() {
        logger.info("开始执行从宇泛数智建平台拉取塔吊设备数据");
        List<AppSyncDTO> appSyncDTOS = syncConfigService.selectByPlatform(SyncPlatform.SZJ.getValue());
        if (CollectionUtils.isEmpty(appSyncDTOS)) {
            logger.info("未获取到配置");
            return;
        }
        Date endDate = new Date();

        for (AppSyncDTO appSyncDTO : appSyncDTOS) {
            List<FseCraneDTO> craneDTOS = fseCraneService.list(appSyncDTO.getProjectId(), DevicePlatform.yufanszj.name());
            if (CollectionUtils.isEmpty(craneDTOS)) {
                logger.info("该项目无宇泛数智建平台塔吊设备,项目id={}", appSyncDTO.getProjectId());
                continue;
            }
            String token = syncConfigService.getSZJSyncToken(appSyncDTO.getProjectId(), appSyncDTO.getPlatform(), appSyncDTO.getAppSecret());
            for (FseCraneDTO craneDTO : craneDTOS) {
                // 实时数据
                getRealData(appSyncDTO.getProjectId(), craneDTO.getSn(), endDate, token);
                // 工作循环
                getWorkData(appSyncDTO.getProjectId(), craneDTO.getSn(), endDate, token);
                // 报警
                getWarnData(appSyncDTO.getProjectId(), craneDTO.getSn(), endDate, token);
            }
        }

    }

    // 实时数据
    public void getRealData(Integer deptId, String deviceKey, Date endDate, String token) {
        Date startDate = DateUtil.addMinutes(endDate, -2);
        String startTime = DateUtil.formatDateTime(startDate);
        String endTime = DateUtil.formatDateTime(endDate);
        // 实时数据
        JSONObject craneRealData = fseCraneSZJDataMgr.getCraneRealData(deviceKey, 1, 1, startTime, endTime, token);
        if (craneRealData == null) {
            logger.info("未获取到塔吊设备数据,项目id={},sn={},startTime={},endTime={}", deptId, deviceKey, startTime, endTime);
            return;
        }
        FseCraneDataDTO fseCraneDataDTO = setRealData(deviceKey, craneRealData);

        amqpTemplate.convertAndSend(QueueConst.FSE_CRANE_REAL_DATA, JSONObject.toJSONString(fseCraneDataDTO));
    }


    public void getWorkData(Integer deptId, String deviceKey, Date endDate, String token) {
        Date startDate = DateUtil.addMinutes(endDate, -2);
        String startTime = DateUtil.formatDateTime(startDate);
        String endTime = DateUtil.formatDateTime(endDate);

        JSONArray craneWorkData = fseCraneSZJDataMgr.getCraneWorkData(deviceKey, 1, 20, startTime, endTime, token);
        if (CollectionUtils.isEmpty(craneWorkData)) {
            logger.info("未获取到塔吊设备工作数据,项目id={},sn={},startTime={},endTime={}", deptId, deviceKey, startTime, endTime);
            return;
        }
        for (Object craneWorkDatum : craneWorkData) {
            JSONObject jsonObject = JSONObject.parseObject(craneWorkDatum.toString());
            // 转换成平台数据
            FseCraneRecordDTO fseCraneRecordDTO = new FseCraneRecordDTO();
            // 设备唯一标识
            fseCraneRecordDTO.setSn(deviceKey);
            fseCraneRecordDTO.setPlatform(DevicePlatform.yufanszj.name());
            // 时间
            String businessTime = jsonObject.getString("businessTime");
            fseCraneRecordDTO.setTime(getDateTime(businessTime));

            // 起吊开始结束时间
            String start_time = jsonObject.getString("liftingTime");
            String end_time = jsonObject.getString("uninstallLiftingTime");
            fseCraneRecordDTO.setStartTime(getDateTime(start_time));
            fseCraneRecordDTO.setEndTime(getDateTime(end_time));
            // 开始结束高度
            Double start_height = jsonObject.getDouble("height");
            Double end_height = jsonObject.getDouble("uninstallHeight");
            fseCraneRecordDTO.setStartHeight(start_height);
            fseCraneRecordDTO.setEndHeight(end_height);
            // 开始结束幅度
            Double start_range = jsonObject.getDouble("towerRange");
            Double end_range = jsonObject.getDouble("uninstallTowerRange");
            fseCraneRecordDTO.setStartRange(start_range);
            fseCraneRecordDTO.setEndRange(end_range);
            // 开始结束转角
            Double start_rotation_angle = jsonObject.getDouble("rotation");
            Double end_rotation_angle = jsonObject.getDouble("uninstallRotation");
            fseCraneRecordDTO.setStartTurnAngle(start_rotation_angle);
            fseCraneRecordDTO.setEndTurnAngle(end_rotation_angle);
            // 最大吊重
            Double weight = jsonObject.getDouble("uninstallLoad");
            fseCraneRecordDTO.setMaxWeight(MathUtil.round(weight * 0.001, 3));
            amqpTemplate.convertAndSend(QueueConst.FSE_CRANE_RECORD_DATA, JSONObject.toJSONString(fseCraneRecordDTO));
        }
    }

    /**
     * 宇泛数智建平台-报警数据
     */
    public void getWarnData(Integer deptId, String deviceKey, Date endDate, String token) {
        Date startDate = DateUtil.addMinutes(endDate, -2);
        String startTime = DateUtil.formatDateTime(startDate);
        String endTime = DateUtil.formatDateTime(endDate);
        JSONArray craneWarnkData = fseCraneSZJDataMgr.getCraneWarnData(deviceKey, 1, 20, startTime, endTime, token);
        if (CollectionUtils.isEmpty(craneWarnkData)) {
            logger.info("未获取到塔吊设备报警数据,项目id={},sn={},startTime={},endTime={}", deptId, deviceKey, startTime, endTime);
            return;
        }
        for (Object craneWarnkDatum : craneWarnkData) {
            JSONObject jsonObject = JSONObject.parseObject(craneWarnkDatum.toString());
            Integer warnType = getWarnType(jsonObject);
            if (warnType == null) {
                logger.info("无报警数据");
                continue;
            }
            // 转换成平台数据
            FseCraneDataDTO fseCraneDataDTO = setRealData(deviceKey, jsonObject);
            // 报警值
            fseCraneDataDTO.setCraneStatus(warnType);
            amqpTemplate.convertAndSend(QueueConst.FSE_CRANE_WARN_DATA, JSONObject.toJSONString(fseCraneDataDTO));
        }
    }

    private Integer getWarnType(JSONObject jsonObject) {
        // 回转限位报警
        Integer rotationLimit = jsonObject.getInteger("rotationLimit");
        if (2 == rotationLimit) {
            return FseWarnRuleType.CRANE_ROTARY_LIMIT.value();
        }
        // 幅度限位报警
        Integer rangeLimit = jsonObject.getInteger("rangeLimit");
        if (2 == rangeLimit) {
            return FseWarnRuleType.CRANE_RANGE.value();
        }
        // 高度限位报警
        Integer heightLimit = jsonObject.getInteger("heightLimit");
        if (2 == heightLimit) {
            return FseWarnRuleType.CRANE_HEIGHT_RANGE.value();
        }
        // 碰撞报警
        Integer crashLimit = jsonObject.getInteger("crashLimit");
        if (2 == crashLimit) {
            return FseWarnRuleType.CRANE_ANTI_COLLISION.value();
        }
        // 载重报警
        Integer loadLimit = jsonObject.getInteger("loadLimit");
        if (2 == loadLimit) {
            return FseWarnRuleType.CRANE_WEIGHT.value();
        }
        // 风速报警
        Integer windSpeedLimit = jsonObject.getInteger("windSpeedLimit");
        if (2 == windSpeedLimit) {
            return FseWarnRuleType.CRANE_WIND_SPEED.value();
        }
        // 力矩报警
        Integer momentLimit = jsonObject.getInteger("momentLimit");
        if (2 == momentLimit) {
            return FseWarnRuleType.CRANE_FORCE_MOMENT.value();
        }
        // 倾斜报警
        Integer leanLimit = jsonObject.getInteger("leanLimit");
        if (2 == leanLimit) {
            return FseWarnRuleType.CRANE_TURN.value();
        }
        return null;
    }

    // 获取日期
    private Date getDateTime(String dateTime) {
        // "2022-03-01T15:41:00.000+0800"
        String replace = dateTime.substring(0, 19).replace("T", " ");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
            parse = sdf.parse(replace);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    // 设置实时数据
    private FseCraneDataDTO setRealData(String deviceKey, JSONObject craneRealData) {
        FseCraneDataDTO fseCraneDataDTO = new FseCraneDataDTO();
        fseCraneDataDTO.setSn(deviceKey);
        fseCraneDataDTO.setPlatform(DevicePlatform.yufanszj.name());

        // 倾角
        Double dipAngle = craneRealData.getDouble("dipAngle");
        fseCraneDataDTO.setDipAngle(dipAngle);
        // 回转
        Double rotation = craneRealData.getDouble("rotation");
        fseCraneDataDTO.setTurnAngle(rotation);
        // 幅度
        Double towerRange = craneRealData.getDouble("towerRange");
        fseCraneDataDTO.setRange(towerRange);
        // 力矩比
        Double momentPercent = craneRealData.getDouble("momentPercent");
        fseCraneDataDTO.setMomentRatio(momentPercent);
        // 时间
        String dateTime = craneRealData.getString("dateTime");
        fseCraneDataDTO.setTime(getDateTime(dateTime));
        // 实时吊重
        Double liftWeight = craneRealData.getDouble("liftWeight");
        fseCraneDataDTO.setWeight(MathUtil.round(liftWeight * 0.001, 3));
        // 风速
        Double windSpeed = craneRealData.getDouble("windSpeed");
        fseCraneDataDTO.setWindSpeed(windSpeed);
        // 高度
        Double height = craneRealData.getDouble("height");
        fseCraneDataDTO.setHeight(height);
        return fseCraneDataDTO;
    }
}

